<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>Vue2.6 HTML页面</title>
    <!-- 引入Vue.js和Vue.js的生命周期插件 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <style>
      .spec {
        margin-bottom: 10px;
        border: 1px solid black;
        padding: 10px;
      }
      .spec-title {
        margin-bottom: 10px;
      }
      .attrList {
        display: flex;
        align-items: center;
      }
      .attr {
        margin-right: 10px;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div id="value"></div>
      <div id="value3"></div>
      <button id="btn">点击+1</button>
    </div>

    <!-- Vue实例及其定义 -->
    <script>
      class Store {
        constructor() {
          this.store = {};
          this.subscribers = new Map();
          this.dispatch = (key, value) => {
            this.store[key] = value;
          };
          Object.freeze(this.store);
          Object.freeze(this.subscribers);
        }
        setDefault(val) {
          this.store = this.reactive(val);
        }
        reactive(val) {
          const _this = this;
          return new Proxy(val, {
            get: function (target, key) {
              if (
                Object.prototype.toString.call(target[key]) ===
                "[object Function]"
              ) {
                // 发送通知，更新所有组件中对应key的值
                _this.depend(key, target[key]);
              }
              return target[key];
            },
            set: function (target, key, value) {
              let result = Reflect.set(target, key, value);
              // 发送通知，更新所有组件中对应key的值
              _this.depend(key, value);
              return result;
            },
          });
        }
        depend(key, value) {
          this.notice(key, value);
        }
        notice(key, value) {
          if (this.subscribers.has(key)) {
            for (let callback of this.subscribers.get(key)) {
              callback(value);
            }
          }
        }
        subscribe(key, callback) {
          if (!this.subscribers.has(key)) {
            this.subscribers.set(key, new Set());
          }
          this.subscribers.get(key).add(callback);
        }
        unsubscribe(key, callback) {
          const subscribersSet = this.subscribers.get(key);
          if (subscribersSet) {
            subscribersSet.delete(callback);
            if (subscribersSet.size === 0) {
              this.subscribers.delete(key);
            }
          }
        }
      }
      const store = new Store();

      store.setDefault({
        key1: 1,
        key3: {},
      });

      document.getElementById("value").innerHTML = store.store.key1;
      document.getElementById("value3").innerHTML = JSON.stringify(
        store.store.key3
      );

      document.querySelector("#btn").addEventListener("click", function () {
        store.dispatch("key1", store.store.key1 + 1);

        const key3 = store.store.key3;
        // key3.c += 1;
        if (key3.d) {
          key3.d += 1;
        } else {
          key3.d = 1;
        }
        if (key3?.e?.a) {
          key3.e.a += 1;
        } else {
          key3.e = {};
          key3.e.a = 1;
        }
      });

      store.subscribe("key1", (val) => {
        document.getElementById("value").innerHTML = store.store.key1;
        console.log(`这里是Home组件，key1更新`, store.store);
      });
      store.subscribe("key3.d", (val) => {
        document.getElementById("value3").innerHTML = JSON.stringify(
          store.store.key3
        );
      });
    </script>
  </body>
</html>
